import axios from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getKey } from '@/utils/storage'
import { logout } from '@/utils/util'
import { envVar } from '@/utils/global'

const instance = axios.create(
  {
    baseURL: envVar.VITE_BASE_URL
  }
)

/**
 * 请求拦截器
 */
instance.interceptors.request.use(config => {
  if (getKey('tokenName') && getKey('tokenValue')) {
    config.headers = {
      [getKey('tokenName')]: getKey('tokenValue')
    }
  }
  return config
}, error => {
  return error
})

/**
 * 响应拦截器
 */
instance.interceptors.response.use(res => {
  // 下载文件，如果请求头没有【content-disposition】 arraybuffer转化为json进行异常抛出
  if (!res.headers['content-disposition']) {
    if (res.data.byteLength) {
      res.data = JSON.parse(new TextDecoder('utf-8').decode(res.data))
    }
    if (res.data.code === 406) {
      ElMessageBox.alert(res.data.message, '登录过期提醒', {
        confirmButtonText: '重新登录',
        callback: () => {
          logout()
        }
      })
    } else if (res.data.code !== 200 && res.data.code !== 406) {
      ElMessage.warning(res.data.message)
    }
  }
  return res
}, error => {
  console.log('响应拦截器异常', error)
  if (error.response && error.response.status === 404) {
    ElMessage.error('未找到服务端地址。')
  } else {
    ElMessage.error('与服务端连接异常。')
  }
  return error
})

/**
 * 公用post请求
 * @param url
 * @param data
 * @returns {Promise<unknown>}
 */
const post = (url, data) => {
  return new Promise((resolve, reject) => {
    instance.request({
      url,
      data,
      method: 'post'
    }).then(res => {
      resolve(res.data)
    }).catch(error => {
      reject(error)
    })
  })
}

/**
 * 公用get请求
 * @param url
 * @param params
 * @returns {Promise<unknown>}
 */
const get = (url, params) => {
  return new Promise((resolve, reject) => {
    instance.request({
      url,
      params,
      method: 'get'
    }).then(res => {
      resolve(res.data)
    }).catch(error => {
      reject(error)
    })
  })
}

/**
 * post文件上传获取进度条
 * @param url
 * @param data
 * @param progress 获取进度信息回调函数
 * @returns {Promise<unknown>}
 */
const postUploadProgress = (url, data, progress) => {
  return new Promise((resolve, reject) => {
    instance.request({
      url,
      data,
      method: 'post',
      onUploadProgress (e) {
        progress(e)
      }
    }).then(res => {
      resolve(res.data)
    }).catch(error => {
      reject(error)
    })
  })
}

/**
 * post请求获取字节流信息
 * @param url
 * @param data
 * @returns {Promise<unknown>}
 */
const postDownloadFile = (url, data) => {
  return new Promise((resolve, reject) => {
    instance.request({
      url,
      data,
      method: 'post',
      responseType: 'arraybuffer'
    }).then(res => {
      resolve(res)
    }).catch(error => {
      reject(error)
    })
  })
}

/**
 * get请求获取字节流信息
 * @param url
 * @param params
 * @returns {Promise<unknown>}
 */
const getDownloadFile = (url, params) => {
  return new Promise((resolve, reject) => {
    instance.request({
      url,
      params,
      method: 'get',
      responseType: 'arraybuffer'
    }).then(res => {
      resolve(res)
    }).catch(error => {
      reject(error)
    })
  })
}

/**
 * 公用get请求下载文件
 * @param url
 * @param params
 * @returns {Promise<void>}
 */
const commonGetDownloadFile = async (url, params) => {
  const result = await getDownloadFile(url, params)
  if (!result.data.code) {
    hrefDownloadFile(result)
  }
}

/**
 * 公用post请求下载文件
 * @param url
 * @param data
 * @returns {Promise<void>}
 */
const commonPostDownloadFile = async (url, data) => {
  const result = await postDownloadFile(url, data)
  // 判断返回的是否是字节流而不是json数据
  if (!result.data.code) {
    hrefDownloadFile(result)
  }
}

/**
 * 字节流进行下载
 * @param result
 */
const hrefDownloadFile = (result) => {
  const filename = result.headers['content-disposition']
  const blob = new Blob([result.data])
  const downloadElement = document.createElement('a')
  const href = window.URL.createObjectURL(blob)
  downloadElement.href = href
  downloadElement.download = decodeURIComponent(filename.split('fileName=')[1])
  document.body.appendChild(downloadElement)
  downloadElement.click()
  document.body.removeChild(downloadElement)
  window.URL.revokeObjectURL(href)
}

export {
  post,
  get,
  postDownloadFile,
  getDownloadFile,
  commonGetDownloadFile,
  commonPostDownloadFile,
  postUploadProgress
}
